home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Source Code / Visual Basic Source Code.iso / vbsource / rpcdcpro / server.cpp < prev    next >
C/C++ Source or Header  |  1998-09-09  |  10KB  |  260 lines

  1. //-----------------------------------------------------------------------------
  2. // This program illustrates a simple server implementation
  3. // The server is listening on the tcp and udp ports
  4. //-----------------------------------------------------------------------------
  5.  
  6. #ifdef WIN32
  7.     #include <windows.h>
  8. #endif
  9. #include <stdio.h>
  10. #include <math.h>
  11.  
  12. #include <rpcdc.h>
  13.  
  14. //-----------------------------------------------------------------------------
  15. // Here is a definition of a structure that must be transmitted to the server
  16. // One possibility is to develop a specific XDR function, used with transmit/
  17. // receive functions
  18. //-----------------------------------------------------------------------------
  19. typedef struct _TEST {
  20.  
  21.     int i1;
  22.     int i2;
  23.     int i3;
  24.  
  25.     float f;
  26.     double d;
  27.  
  28. } TEST;
  29.  
  30. //-----------------------------------------------------------------------------
  31. // First write the XDR function - standard structure
  32. // The parameters are as follows :
  33. //      h : (void *) points to the host binary representation of the data
  34. //      n : (void *) points to the network binary representation of the data
  35. //      code : indicates the operation to perform (3 possibilities)
  36. //              --> XDR_ENCODE : conversion h -> n
  37. //              --> XDR_DECODE : conversion n -> h
  38. //              --> XDR_MEMORY : just returns the size of the object
  39. //-----------------------------------------------------------------------------
  40. size_t _xdr_TEST (void *h, void *n, int code)
  41.  
  42. {       
  43.     TEST *hi=(TEST *)h;             // first convert pointers
  44.     char *ni=(char *)n;
  45.     size_t size;
  46.     
  47.     switch (code) {
  48.  
  49.     case XDR_ENCODE: 
  50.     case XDR_DECODE:
  51.         
  52.         size=_xdr_int(NULL,NULL,XDR_MEMORY);
  53.         _xdr_int((void *)&hi->i1,(void *)ni,code);   ni+=size;
  54.         _xdr_int((void *)&hi->i2,(void *)ni,code);   ni+=size;
  55.         _xdr_int((void *)&hi->i3,(void *)ni,code);   ni+=size;
  56.         
  57.         size=_xdr_float(NULL,NULL,XDR_MEMORY);
  58.         _xdr_float((void *)&hi->f,(void *)ni,code);  ni+=size;
  59.         
  60.         size=_xdr_double(NULL,NULL,XDR_MEMORY);
  61.         _xdr_double((void *)&hi->d,(void *)ni,code); ni+=size;
  62.         return 0;
  63.  
  64.     case XDR_MEMORY:
  65.     default:
  66.         return 3*_xdr_int(NULL,NULL,XDR_MEMORY)+
  67.                  _xdr_float(NULL,NULL,XDR_MEMORY)+
  68.                  _xdr_double(NULL,NULL,XDR_MEMORY);
  69.     }
  70. }
  71.  
  72. //-----------------------------------------------------------------------------
  73. // Now the function to send a TEST structure becomes very simple !
  74. // The following example returns 1 if success, 0 if a problem occurs.
  75. // Binary conversion is automatically performed through the XDR routine
  76. // written above.
  77. // Warning : remember to call _rpc_flush() !
  78. //-----------------------------------------------------------------------------
  79. int _rpcsend_TEST (SOCKET Socket, 
  80.                    RPC_MSG *rpc_msg, XDR_BUFFER *xdr_buffer,
  81.                    TEST *TestParameter)
  82.  
  83. {   
  84.     return _rpcsend_buffer(Socket,rpc_msg,xdr_buffer,TestParameter,_xdr_TEST)==
  85.            _xdr_TEST(NULL,NULL,XDR_MEMORY);
  86. }
  87.  
  88. //-----------------------------------------------------------------------------
  89. // Similarly, the function to receive a TEST structure is also simple.
  90. // Binary conversion is automatically performed through the XDR routine
  91. // written above.
  92. //-----------------------------------------------------------------------------
  93. int _rpcrecv_TEST (SOCKET Socket, 
  94.                    XDR_BUFFER *xdr_buffer,
  95.                    TEST *TestParameter)
  96.          
  97. {
  98.     return _rpcrecv_buffer(Socket,xdr_buffer,TestParameter,_xdr_TEST)==
  99.            _xdr_TEST(NULL,NULL,XDR_MEMORY);         
  100. }
  101.  
  102. //-----------------------------------------------------------------------------
  103. // This is one of the most important functions : each time a message is
  104. // received by the server, this function is called
  105. // The first parameter rpc_func identifies the message
  106. // The second parameter idClient identifies the client (the server can accept
  107. // connections with multiple clients at the same time)
  108. //-----------------------------------------------------------------------------
  109. static void Dispatch (int rpc_func, int idClient)
  110.  
  111. {
  112.     SOCKET socket;
  113.     RPC_MSG *rpc_msg;
  114.     XDR_BUFFER *xdr_buffer;
  115.     char *client_buffer;
  116.     int I;
  117.     TEST Test;
  118.     
  119. // The first thing to do is to retrieve the parameters of the client
  120.     _GetClientInfo(idClient,
  121.                    &socket,
  122.                    &rpc_msg,
  123.                    &xdr_buffer,
  124.                    &client_buffer);
  125.  
  126. // Now, the function reduces to a big switch depending of the value of rpc_func
  127.     switch (rpc_func) {
  128.  
  129. // First kind of message (prefer constants defined by #define instead of numerical constants)
  130. // This message requires to read additionnal parameters (int + TEST strcuture) from the socket
  131. // The response of the server to the client : just add 1 to the int sent by the client, and then return it
  132. // Similar changes to the TEST structure
  133. // Note the call to _rpc_flush() !
  134.     case 1:
  135.         _rpcrecv_int(socket,xdr_buffer,&I);
  136.         _rpcrecv_TEST(socket,xdr_buffer,&Test);
  137.         printf("Data received from client : %d\n",I);
  138.         printf("TEST structure            : %d %d %d %g %lg\n",Test.i1,Test.i2,Test.i3,Test.f,Test.d);
  139. // Now change the values
  140.         I++;
  141.         Test.i1*=2; 
  142.         Test.i2*=3;
  143.         Test.i3*=4;
  144.         Test.f=1.0f/Test.f;
  145.         Test.d=sqrt(Test.d);
  146. // Now returns to changes parameters to client
  147.         _rpcsend_int(socket,rpc_msg,xdr_buffer,I);
  148.         _rpcsend_TEST(socket,rpc_msg,xdr_buffer,&Test);
  149.         _rpc_flush(socket,rpc_msg);
  150.         break;
  151.  
  152. // Other messages and associated code ...
  153.         
  154.     default:
  155.         return;
  156.     }
  157. }                        
  158.  
  159. //-----------------------------------------------------------------------------
  160. // This accepts or not a connection from one client on the network, whose ip
  161. // address is transmitted as a character string parameter. The return value is
  162. // 0 (connection refused) or 1 (connection accepted)
  163. //-----------------------------------------------------------------------------
  164. static int AcceptConnection (char *ip)
  165.  
  166. {
  167.     return 1;    
  168. }
  169.  
  170. //-----------------------------------------------------------------------------
  171. // This function is called each time a message is received on the udp socket
  172. // of the server (if it exists).
  173. // In this example, the server sends an answer made of one long int, followed
  174. // by a 128 characters string.
  175. //-----------------------------------------------------------------------------
  176. void udpManager (SOCKET udpSocket) 
  177.  
  178. {
  179.     sockaddr_in src_addr;
  180.     long int udpQuery;
  181.     int stat,len;
  182.     struct {
  183.         long int udpResponse;
  184.         char szb[128];
  185.     } udp;
  186.  
  187. // First I read the data from the udp socket. In this example, the client is assumed to send
  188. // only a 32 bits message
  189.     len=sizeof(src_addr);
  190.     stat=recvfrom(udpSocket,(char *)&udpQuery,sizeof(long int),0,(struct sockaddr *)&src_addr,&len);
  191.     if (stat!=sizeof(long int)) return;
  192. // Note the use of ntohl(), required by the XDR mechanism
  193.     udpQuery=ntohl(udpQuery);
  194.  
  195. // Depending on the received message, I generate the answer, replying (udpQuery+1)
  196.     switch (udpQuery) {
  197.     case 1:
  198.         udp.udpResponse=htonl(1+udpQuery);  // response=query+1
  199.         strcpy(udp.szb,"udp query #1");     // text of the response
  200.         break;
  201.     default:
  202.         udp.udpResponse=htonl(0);           // response=0
  203.         strcpy(udp.szb,"");                 // empty text
  204.     }
  205.  
  206. // Now send the response to the client who sent the udp request
  207.     sendto(udpSocket,(char *)&udp,sizeof(udp),MSG_DONTROUTE,(struct sockaddr *)&src_addr,sizeof(sockaddr_in));
  208. }
  209.  
  210. //-----------------------------------------------------------------------------
  211. // This function starts the server with a specific service
  212. //-----------------------------------------------------------------------------
  213. static void Start (char *service)
  214.  
  215. {
  216.     int stat;
  217.     SOCKET tcpSock